import re
import json
import uuid
from typing import Dict, List, Optional, Tuple, Any
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_, or_
from sqlalchemy.orm import selectinload
from datetime import datetime
from loguru import logger

from app.models.db import UserSession, UserMsg, DataSet, DataSource, TaskConfig, ApiFunction
from app.ai.ai_getdata import AIGetData
from app.models.user import get_user_profile_by_identifier


class IntentRecognitionEngine:
    """意图识别引擎 - 识别用户意图并分解为可执行任务"""
    
    def __init__(self, base_url=None, api_key=None):
        # 初始化AI获取数据客户端
        from config import AI_BASEURL, AI_API_KEY
        self.ai_client = AIGetData(
            base_url=base_url or AI_BASEURL,
            api_key=api_key or AI_API_KEY
        )
       
    async def recognize_intent_without_saving(
        self, 
        user_input: str, 
        session_id: str, 
        user_id: str,
        db: AsyncSession
    ) -> List[Dict[str, Any]]:
        """
        识别用户意图但不保存用户消息，用于已经保存过用户消息的场景
        
        Args:
            user_input: 用户输入
            session_id: 会话ID
            user_id: 用户ID
            db: 数据库会话
            
        Returns:
            List[Dict[str, Any]]: 意图识别结果列表
        """
        try:
            # 1. 获取会话上下文
            session_context = await self._get_session_context(session_id, user_id, db)
            
            # 2. 获取可用任务配置
            available_tasks = await self._get_available_tasks(db)
            
            # 3. 进行多意图识别
            intent_results = await self._analyze_intent_with_ai(
                user_input, session_context, available_tasks
            )
            
            return intent_results
            
        except Exception as e:
            logger.error(f"意图识别失败: {str(e)}")
            return [{
                "intent_id": "error_intent_1",
                "intent_type": "unknown",
                "confidence": 0.0,
                "status": "error",
                "analysis_reason": f"意图识别过程中发生错误: {str(e)}",
                "next_action": "clarify",
                "user_message": "抱歉，系统暂时无法理解您的需求。请重新描述您想要执行的操作，我会尽力帮助您。"
            }]
    
    async def _get_session_context(self, session_id: str, user_id: str, db: AsyncSession) -> Dict[str, Any]:
        """获取会话上下文信息"""
        try:
            # 获取会话信息
            session_query = select(UserSession).where(UserSession.id == session_id)
            session_result = await db.execute(session_query)
            user_session = session_result.scalar_one_or_none()
            
            if not user_session:
                return {"messages": [], "datasets": []}
            
            # 获取最近的消息记录（最多10条）
            messages_query = (
                select(UserMsg)
                .where(UserMsg.session_id == session_id,UserMsg.message_type == 'user')
                .order_by(UserMsg.timestamp.desc())
                .limit(10)
            )
            messages_result = await db.execute(messages_query)
            messages = messages_result.scalars().all()
            
            # 获取用户有权限访问的数据集（使用公共工具方法）
            from app.utils.dataset_access import get_user_accessible_datasets, get_user_accessible_knowledge_bases
            
            session_dataset_ids = user_session.get_dataset_ids() if user_session and user_session.dataset_ids else None
            available_datasets = await get_user_accessible_datasets(
                user_id=user_id,
                session=db,
                session_dataset_ids=session_dataset_ids
            )
            
            # 获取用户有权限访问的知识库ID列表
            accessible_knowledge_bases = await get_user_accessible_knowledge_bases(
                user_id=user_id,
                session=db
            )
            
            user_profile = await get_user_profile_by_identifier(user_id)

            return {
                "session": user_session,
                "messages": [msg.dict() for msg in reversed(messages)],
                "datasets": available_datasets,
                "user_profile": user_profile,
                "dataset_ids": user_session.get_dataset_ids() if user_session else [],
                "accessible_knowledge_bases": accessible_knowledge_bases  # 新增知识库权限列表
            }
            
        except Exception as e:
            logger.error(f"获取会话上下文失败: {str(e)}")
            return {"messages": [], "datasets": []}
    
    async def _get_available_tasks(self, db: AsyncSession) -> List[Dict[str, Any]]:
        """获取可用的API函数任务配置（不包括data_query类型）"""
        try:
            # 只获取api_function类型的任务配置，按优先级排序
            tasks_query = (
                select(TaskConfig)
                .where(and_(
                    TaskConfig.is_active == True,
                    TaskConfig.task_type == "api_function"  # 只获取API函数任务
                ))
                .order_by(TaskConfig.priority.desc())
            )
            tasks_result = await db.execute(tasks_query)
            tasks = tasks_result.scalars().all()
            
            available_tasks = []
            for task in tasks:
                # 显式查询API函数信息，避免懒加载问题
                api_funcs_query = (
                    select(ApiFunction)
                    .where(and_(
                        ApiFunction.task_config_id == task.id,
                        ApiFunction.is_active == True
                    ))
                )
                api_funcs_result = await db.execute(api_funcs_query)
                api_functions_data = api_funcs_result.scalars().all()
                
                api_functions = []
                for api_func in api_functions_data:
                    # 解析JSON字段
                    keywords = json.loads(api_func.intent_keywords) if api_func.intent_keywords else []
                    patterns = json.loads(api_func.intent_patterns) if api_func.intent_patterns else []
                    examples = json.loads(api_func.intent_examples) if api_func.intent_examples else []
                    required_params = json.loads(api_func.required_params) if api_func.required_params else []
                    
                    api_functions.append({
                        "id": api_func.id,
                        "name": api_func.function_name,
                        "description": api_func.description,
                        "keywords": keywords,
                        "patterns": patterns,
                        "examples": examples,
                        "required_params": required_params
                    })
                
                if api_functions:  # 只有当有可用的API函数时才添加任务
                    task_info = {
                        "id": task.id,
                        "type": task.task_type,
                        "name": task.task_name,
                        "description": task.description,
                        "priority": task.priority,
                        "api_functions": api_functions
                    }
                    available_tasks.append(task_info)
            
            return available_tasks
            
        except Exception as e:
            logger.error(f"获取可用任务失败: {str(e)}")
            return []
    
    async def _analyze_intent_with_ai(
        self, 
        user_input: str, 
        context: Dict[str, Any], 
        available_tasks: List[Dict[str, Any]]
    ) -> List[Dict[str, Any]]:
        """使用AI分析用户意图，支持多意图识别"""
        try:
            # 调用AI客户端进行完整的意图识别
            intent_results = self.ai_client.generate_intent_analysis(
                user_input, context, available_tasks
            )
            
            # 处理AI返回的结果
            if isinstance(intent_results, list) and len(intent_results) > 0:
                logger.info(f"AI成功识别到{len(intent_results)}个意图")
                return intent_results
            elif isinstance(intent_results, dict):
                # 单个意图对象，转换为列表
                logger.info("AI成功识别到1个意图")
                return [intent_results]
            else:
                # AI返回格式不正确或为空
                logger.warning("AI返回格式不正确或为空，返回未知意图")
                return [self._get_unknown_intent("AI返回格式不正确")]
                
        except Exception as e:
            logger.error(f"AI意图分析失败: {str(e)}")
            return [self._get_unknown_intent(f"意图分析失败: {str(e)}")]
    
    def _get_unknown_intent(self, error_message: str = "无法识别用户意图") -> Dict[str, Any]:
        """获取默认的未知意图响应"""
        return {
            "intent_id": f"unknown_intent_{uuid.uuid4().hex[:8]}",
            "intent_type": "unknown",
            "confidence": 0.0,
            "priority": 1,
            "task_id": None,
            "api_function_id": None,
            "dataset_id": None,
            "extracted_params": {},
            "missing_params": [],
            "analysis_reason": error_message,
            "dependencies": [],
            "next_action": "clarify",
            "user_message": "抱歉，我没有完全理解您的需求。我可以帮您：\n\n📋 **功能调用**\n📊 **数据查询分析**\n📈 **图表生成**\n📄 **报告生成**\n📚 **知识库查询**\n\n请详细描述您想要执行的操作，我会尽力帮助您。",
            "execution_order": 1
        }
    